package bairui.international.config;

import javax.servlet.http.HttpSession;

import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultHandler;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;

public class Config_SecurityBase extends Config_Base {

    protected void beforeClass() throws Exception {
        mockMvc = MockMvcBuilders
        		.webAppContextSetup(wac)
        		.apply(SecurityMockMvcConfigurers.springSecurity())
        		.alwaysDo(MockMvcResultHandlers.print())
        		.alwaysDo(new ResultHandler() {
					@Override
					public void handle(MvcResult result) throws Exception {
						refreshSecurityContext(result);
					}
				})
        		.alwaysExpect(new ResultMatcher() {
					@Override
					public void match(MvcResult result) throws Exception {
						Object handler = result.getHandler();
						if(handler instanceof HandlerMethod){
							Class<?> returnType = ((HandlerMethod)handler).getMethod().getReturnType();
							/*
							 * 排除 404 等状态
							 */
							if(returnType == ModelAndView.class){
								// redirect方式
								if(result
										.getModelAndView()
										.getViewName()
										.startsWith("redirect:")
								){
									MockMvcResultMatchers.status().is3xxRedirection().match(result);
								}else{
									MockMvcResultMatchers.status().isOk().match(result);;
								}
							}else{
								MockMvcResultMatchers.status().isOk().match(result);
							}
						}
					}
				})
        		.build();
    }
	
//    @PreDestroy
//	protected void afterClass() throws Exception {
//		SecurityContextHolder.clearContext();
//	}
    
    /**
	 * 解决可能出现的，因为 SecurityContextPersistenceFilter 过滤器清理 SecurityContext 
	 * 导致的 SecurityContext 为空, 不能对实体操作的bug
	 */
    private static void refreshSecurityContext(MvcResult mvcResult){
    	refreshSecurityContext(mvcResult.getRequest().getSession());
    }
    private static void refreshSecurityContext(HttpSession session){
		SecurityContext securityContext = (SecurityContext)session.getAttribute("SPRING_SECURITY_CONTEXT");
   		if(null != securityContext && null != securityContext.getAuthentication()){
   			SecurityContextHolder.setContext(securityContext);
   		}
    }
    
}
